//
//  MJGHTMLReader.m
//  MJGHTMLReader
//
//  Created by Mei Jigao on 15/4/21.
//  Copyright (c) 2015年 MeiJigao. All rights reserved.
//

#import "MJGHTMLReader.h"
#import <UIKit/UIKit.h>
#import "HTMLReader.h"

@interface MJGHTMLReader () <NSURLConnectionDataDelegate, NSURLConnectionDelegate> {
    
    NSString *contentType;
}

@property (nonatomic, strong) NSURL *documentUrl;
@property (nonatomic, strong) HTMLDocument *rootDocument;
@property (nonatomic, weak) id<MJGHTMLReaderUrlDocumentDelegate> urlDocDelegate;

@end

@implementation MJGHTMLReader

#pragma mark - init
- (instancetype)init {
    
    self = [super init];
    if (self) {
        
    }
    return self;
}

#pragma mark - document
- (HTMLDocument *)setDocumentElementWithString:(NSString *)string {
    
    self.rootDocument = [[HTMLDocument alloc] initWithString:string];
    return self.rootDocument;
}

- (HTMLDocument *)setDocumentElementWithData:(NSData *)htmlData {
    
    self.rootDocument = [[HTMLDocument alloc] initWithData:htmlData contentTypeHeader:nil];
    return self.rootDocument;
}

- (void)setDocumentElementWithUrl:(NSURL *)htmlUrl delegate:(id<MJGHTMLReaderUrlDocumentDelegate>)delegate {
    
    self.documentUrl = htmlUrl;
    self.urlDocDelegate = delegate;
    
    self.rootDocument = nil;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0) {
        
        NSURLRequest *urlRequest = [NSURLRequest requestWithURL:htmlUrl];
        NSURLConnection *connection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
        [connection start];
    }
    else {
        
        __block typeof(self) weakSelf = self;
        __block typeof(contentType) blockType = contentType;
        NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
        NSURLSessionDataTask *task = [urlSession dataTaskWithURL:htmlUrl completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            
            if (weakSelf.rootDocument) {
                return;
            }
            
            if (error) {
                
                weakSelf.rootDocument = nil;
            }
            else {
                
                blockType = nil;
                if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
                    NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields];
                    blockType = headers[@"Content-Type"];
                }
                
                weakSelf.rootDocument = [HTMLDocument documentWithData:data contentTypeHeader:blockType];
            }
            
            if (weakSelf.urlDocDelegate && [weakSelf.urlDocDelegate respondsToSelector:@selector(htmlFieldRead:didFinisheLoading:)]) {
                
                [weakSelf.urlDocDelegate htmlFieldRead:weakSelf didFinisheLoading:error];
            }
        }];
        
        [task resume];
    }
}

#pragma mark - element
- (HTMLElement *)htmlElement {
    
    return [[self elementNodesIn:self.rootDocument tagName:@"html"] firstObject];
}

- (HTMLElement *)headElement {
    
    return [[self elementNodesIn:[self htmlElement] tagName:@"head"] firstObject];
}

- (HTMLElement *)bodyElement {
    
    return [[self elementNodesIn:[self htmlElement] tagName:@"body"] firstObject];
}

#pragma mark - attributes
- (NSArray *)elementNodesIn:(HTMLNode *)htmlNode {
    
    NSMutableArray *elementNodes = [[NSMutableArray alloc] init];
    for (HTMLElement *htEle in [htmlNode childElementNodes]) {
        
        [elementNodes addObject:htEle];
    }
    
    return elementNodes;
}

- (NSArray *)elementNodesIn:(HTMLNode *)htmlNode tagName:(NSString *)tagName {
    
    NSMutableArray *elementNodes = [[NSMutableArray alloc] init];
    for (HTMLElement *htEle in [htmlNode childElementNodes]) {
        
        if ([[htEle tagName] isEqualToString:tagName]) {
            
            [elementNodes addObject:htEle];
        }
    }
    
    return elementNodes;
}

- (NSArray *)attributesDictArrayIn:(HTMLNode *)htmlNode {
    
    NSMutableArray *dictArray = [[NSMutableArray alloc] init];
    for (HTMLElement *htEle in [htmlNode childElementNodes]) {
        
        [dictArray addObject:[htEle attributes]];
    }
    
    return dictArray;
}

- (NSArray *)attributesDictArrayIn:(HTMLNode *)htmlNode tagName:(NSString *)tagName {
    
    NSMutableArray *dictArray = [[NSMutableArray alloc] init];
    for (HTMLElement *htEle in [htmlNode childElementNodes]) {
        
        if ([[htEle tagName] isEqualToString:tagName]) {
            
            [dictArray addObject:[htEle attributes]];
        }
    }
    
    return dictArray;
}

- (NSString *)attributeIn:(HTMLNode *)htmlNode attributeName:(NSString *)attributeName specifyAttributeName:(NSString *)specifyName specifyAttribute:(NSString *)specifyAttribute {
    
    NSString *retAttribute = nil;
    for (HTMLElement *htEle in [htmlNode childElementNodes]) {
        
        NSDictionary *attributs = [htEle attributes];
        if ([[attributs allKeys] containsObject:specifyName] && [[attributs objectForKey:specifyName] isEqualToString:specifyAttribute]) {
            
            retAttribute = [attributs objectForKey:attributeName];
            break;
        }
        
        retAttribute = [self attributeIn:htEle attributeName:attributeName specifyAttributeName:specifyName specifyAttribute:specifyAttribute];
        if (retAttribute) {
            
            break;
        }
    }
    
    return retAttribute;
}

#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    
    self.rootDocument = nil;
    
    if (self.urlDocDelegate && [self.urlDocDelegate respondsToSelector:@selector(htmlFieldRead:didFinisheLoading:)]) {
        
        [self.urlDocDelegate htmlFieldRead:self didFinisheLoading:error];
    }
}

#pragma mark - NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    
    contentType = nil;
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        
        NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields];
        contentType = headers[@"Content-Type"];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    
    if (self.rootDocument) {
        return;
    }
    
    self.rootDocument = [HTMLDocument documentWithData:data contentTypeHeader:contentType];
    
    if (self.urlDocDelegate && [self.urlDocDelegate respondsToSelector:@selector(htmlFieldRead:didFinisheLoading:)]) {
        
        [self.urlDocDelegate htmlFieldRead:self didFinisheLoading:nil];
    }
}

#pragma mark - Log
- (void)logOutHTMLElement {
    
    [self logOutHTMLElement:self.rootDocument];
}

- (void)logOutHTMLElement:(HTMLNode *)htNode {
    
    for (HTMLElement *htEle in [htNode childElementNodes]) {
        
        NSLog(@"%s, %d, %@", __FUNCTION__, __LINE__, [htEle tagName]);
        NSLog(@"%s, %d, %@", __FUNCTION__, __LINE__, [htEle textContent]);
        NSLog(@"%s, %d, %@", __FUNCTION__, __LINE__, [htEle attributes]);
        [self logOutHTMLElement:htEle];
    }
}

#pragma mark - end

@end
